package com.bff.gaia.runtime.maqy.util;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

public class ObjectAnalyzer {
	private static ArrayList<Object> visited = new ArrayList<>();

	// 以Json格式展示任意obj的状态信息，便于调试
	public static String toJsonStr(Object obj) {
		visited.clear();

		return toJsonStrInternal(obj);
	}

	private static String toJsonStrInternal(Object obj) {
		String res = "";

		// check
		if (obj == null)
			return "null";
		if (visited.contains(obj))
			return "\"...\"";

		// mark
		visited.add(obj);

		Class cl = obj.getClass();

		// is String
		if (cl == String.class)
			return "\"" + obj.toString() + "\"";

		// is Array
		if (cl.isArray()) {
			res = "{\"Class\":\"Array\",\"ComponentType\":\"" + cl.getComponentType().getName() + "\",\"value\":{";
			for (int i = 0; i < Array.getLength(obj); i++) {
				Object val = Array.get(obj, i);
				res += "\"" + i + "\":";
				if (cl.getComponentType().isPrimitive()) {
					res += val;
				} else {
					res += toJsonStrInternal(val);
				}
				res += ",";
			}

			if (res.endsWith(","))
				res = res.substring(0, res.length() - 1);
			res += "}}";

			return res;
		}

		// is Enum or normal Object
		if (cl.isEnum()) {
			res = "{\"Enum\":\"" + cl.getName() + "\",\"Name\":" + "\"" + ((Enum) obj).name() +"\",";
		} else {
			res = "{\"Class\":\"" + cl.getName() + "\",";
		}
		Field[] fields = cl.getDeclaredFields();
		AccessibleObject.setAccessible(fields, true);
		// show all fields
		for (Field field : fields) {
			if (Modifier.isStatic(field.getModifiers()))
				continue;

			// show name
			res += "\"" + field.getName() + "\":";

			// show value
			Class fieldCl = field.getType();
			try {
				Object val = field.get(obj);
				if (fieldCl.isPrimitive())
					res += val;
				else
					res += toJsonStrInternal(val);
			} catch (Exception e) {
				e.printStackTrace();
			}

			res += ",";
		}
		if (res.endsWith(","))
			res = res.substring(0, res.length() - 1);
		res += "}";

		return res;
	}
}